package org.daochong.lang;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class DefaultEventHandler implements EventHandler {

	protected ThreadPool threadPool;
	protected Map<Class<?>, List<EventListener<Object>>> listeners;

	public ThreadPool getThreadPool() {
		return threadPool;
	}

	public void setThreadPool(ThreadPool threadPool) {
		this.threadPool = threadPool;
	}

	public Map<Class<?>, List<EventListener<Object>>> getListeners() {
		return listeners;
	}

	public void setListeners(Map<Class<?>, List<EventListener<Object>>> listeners) {
		this.listeners = listeners;
	}

	public void notify(Object source) {
		notify(source, null);
	}

	private List<EventListener<Object>> getObjectListeners(Object obj) {
		List<EventListener<Object>> list = new ArrayList<EventListener<Object>>();
		for (Class<?> clazz : this.listeners.keySet()) {
			if (BeanUtil.isMatch(obj, clazz)) {
				list.addAll(this.listeners.get(clazz));
			}
		}
		return list;
	}

	public void notify(Object source, String operation) {
		List<EventListener<Object>> list = getObjectListeners(source);
		if (list != null) {
			for (EventListener<Object> ls : list) {
				if (operation == null || ls.getOperation() == null || ls.getOperation().equals(operation)
						|| (ls.getOperation().endsWith("*") && operation
								.startsWith(ls.getOperation().substring(0, ls.getOperation().length() - 1)))) {
					if (this.getThreadPool() != null) {
						EventData ed = new EventData();
						ed.setListener(ls);
						ed.setSource(source);
						this.getThreadPool().execute(ed);
					} else {
						System.out.println("DefaultEventHanlder:threadPool is null");
						ls.action(source, operation);
					}
				}
			}
		}
	}

}

class EventData implements Runnable {
	private EventListener<Object> listener;
	private Object source;
	private String operation;

	public String getOperation() {
		return operation;
	}

	public void setOperation(String operation) {
		this.operation = operation;
	}

	public EventListener<Object> getListener() {
		return listener;
	}

	public void setListener(EventListener<Object> listener) {
		this.listener = listener;
	}

	public Object getSource() {
		return source;
	}

	public void setSource(Object source) {
		this.source = source;
	}

	public void run() {
		listener.action(source, this.getOperation());
	}
}